home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
cmds
/
oldwish
/
wishDisplay.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-23
|
56KB
|
1,805 lines
/*
* wishDisplay.c --
*
* Routines for layout and display for the file system flat display.
*
* Copyright 1987 Regents of the University of California
* All rights reserved.
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /a/newcmds/wish/RCS/wishDisplay.c,v 1.6 89/01/19 16:53:10 mgbaker Exp Locker: mgbaker $ SPRITE (Berkeley)";
#endif not lint
typedef int Boolean;
#define FALSE 0
#define TRUE 1
#include <sys/types.h>
#include <sys/stat.h>
#include "time.h"
#include <sys/dir.h> /* included only for MAXNAMLEN */
#include "string.h"
#include "sx.h"
#include "util.h"
#include "monitorClient.h"
#include "wishInt.h"
/*
* Include cursor declarations and definitions.
* flat.cursor defines the regular flat display cursor and wait.cursor defines
* the cursor used while the display is busy.
*/
#include "flat.cursor"
#include "wait.cursor"
/*
* The flat cursor is the regular cursor when the display is
* idle. The wait cursor indicates that the display is working
* away on something. The regular cursor can be redefined by
* users, if they wish. (Well... sometime that will be possible...)
*/
static Cursor flatCursor = -1;
static Cursor waitCursor = -1;
/* Default commands in the overall command table. */
static CmdInfo commands[] = {
{"bind", WishBindCmd},
{"changeDirectory", WishChangeDirCmd},
{"quit", WishQuitCmd},
{"close", WishCloseCmd},
{"redraw", WishRedrawCmd},
{"selection", WishSelectionCmd},
{"resize", WishResizeCmd},
{"toggleSelection", WishToggleSelectionCmd},
{"toggleSelEntry", WishToggleSelEntryCmd},
{"groupBind", WishGroupBindCmd},
{"open", WishOpenCmd},
{"sortFiles", WishSortFilesCmd},
{"setFields", WishChangeFieldsCmd},
{"defineGroup", WishDefineGroupCmd},
{"changeGroup", WishChangeGroupCmd},
{"pattern", WishPatternCompareCmd},
{"menu", WishMenuCmd},
{"exec", WishExecCmd},
{(char *) NULL, (int (*)()) NULL}
};
/*
* Number of open windows, for graceful exit when we close them all.
*/
int wishWindowCount = 0;
/*
/*
* Used before defined.
*/
static void GetColumnWidthInfo();
static int GetMaxEntryWidth();
static void FigureWindowSize();
/*
*----------------------------------------------------------------------
*
* WishCreate --
*
* Create an wish window.
*
* Results:
* A pointer to the created WishWindow structure, or NULL if the
* call failed.
*
* Side effects:
* A new wish window will be created and displayed.
*
*----------------------------------------------------------------------
*/
WishWindow *
WishCreate(aWindow, dir)
WishWindow *aWindow; /* parent window */
char *dir; /* directory to start in */
{
WishWindow *newWindow;
struct stat dirAtts;
Tx_WindowInfo info;
int result;
static char *args[] = {"/bin/csh", "-i", NULL};
XSizeHints sizeHints;
XGCValues gcValues;
newWindow = (WishWindow *) malloc(sizeof (WishWindow));
if (dir != NULL) {
/* quick hack until i fix selection problems */
if (dir[strlen(dir) - 1] == ' ') {
dir[strlen(dir) - 1] = '\0';
}
if (Util_CanonicalDir(dir, NULL, newWindow->dir) == NULL) {
/* error message returned in newWindow->dir */
/* if null, then we were called from main() anyway */
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay, newWindow->dir);
}
strcpy(aWindow->interp->result, newWindow->dir);
free(newWindow);
return NULL;
}
} else {
strcpy(newWindow->dir, aWindow->dir);
}
if (lstat(newWindow->dir, &dirAtts)
!= 0) {
/* if null, then we were called from main() anyway */
if (aWindow->interp == NULL) {
sprintf(wishErrorMsg,
"Can't get attributes for %s. Maybe it doesn't exist",
newWindow->dir);
Sx_Panic(wishDisplay, wishErrorMsg);
}
sprintf(aWindow->interp->result,
"Can't get attributes for %s. Maybe it doesn't exist",
newWindow->dir);
free(newWindow);
return NULL;
}
/* Put name of dir in the editable string for the title display window */
strcpy(newWindow->editDir, newWindow->dir);
if ((dirAtts.st_mode & S_IFMT) != S_IFDIR) { /* not a directory */
if (aWindow->interp == NULL) {
sprintf(wishErrorMsg, "%s is not a directory", newWindow->dir);
Sx_Panic(wishDisplay, wishErrorMsg);
}
sprintf(aWindow->interp->result, "%s is not a directory",
newWindow->dir);
free(newWindow);
return NULL;
}
if (chdir(newWindow->dir) != 0) {
if (aWindow->interp == NULL) {
sprintf(wishErrorMsg,
"Couldn't change directories to %s", newWindow->dir);
Sx_Panic(wishDisplay, wishErrorMsg);
}
sprintf(aWindow->interp->result,
"Couldn't change directories to %s", newWindow->dir);
free(newWindow);
return NULL;
}
strcpy(wishCurrentDirectory, newWindow->dir);
newWindow->foreground = aWindow->foreground;
newWindow->background = aWindow->background;
newWindow->selection = aWindow->selection;
newWindow->border = aWindow->border;
newWindow->borderWidth = aWindow->borderWidth;
newWindow->fontPtr = aWindow->fontPtr;
newWindow->titleForeground = aWindow->titleForeground;
newWindow->titleBackground = aWindow->titleBackground;
newWindow->titleBorder = aWindow->titleBorder;
newWindow->titleFontPtr = aWindow->titleFontPtr;
newWindow->txForeground = aWindow->txForeground;
newWindow->txBackground = aWindow->txBackground;
newWindow->txBorder = aWindow->txBorder;
newWindow->menuForeground = aWindow->menuForeground;
newWindow->menuBackground = aWindow->menuBackground;
newWindow->sortForeground = aWindow->sortForeground;
newWindow->sortBackground = aWindow->sortBackground;
newWindow->fieldsForeground = aWindow->fieldsForeground;
newWindow->fieldsBackground = aWindow->fieldsBackground;
newWindow->entryForeground = aWindow->entryForeground;
newWindow->entryBackground = aWindow->entryBackground;
newWindow->scrollForeground = aWindow->scrollForeground;
newWindow->scrollBackground = aWindow->scrollBackground;
newWindow->scrollElevator = aWindow->scrollElevator;
newWindow->geometry = aWindow->geometry;
newWindow->firstElement = UNINITIALIZED;
newWindow->numGroups = UNINITIALIZED;
newWindow->numHiddenGroups = 0;
newWindow->hideEmptyGroupsP = aWindow->hideEmptyGroupsP;
newWindow->dontDisplayChangesP = FALSE;
newWindow->notifierP = FALSE;
/*
* Create the first window and subwindows and use the window id to
* identify the application's data.
*/
if (newWindow->geometry != NULL) {
(void) XParseGeometry(newWindow->geometry, &sizeHints.x, &sizeHints.y,
&sizeHints.width, &sizeHints.height);
}
newWindow->surroundingWindow = XCreateSimpleWindow(wishDisplay,
DefaultRootWindow(wishDisplay), sizeHints.x, sizeHints.y,
sizeHints.width, sizeHints.height, newWindow->borderWidth,
newWindow->border, newWindow->background);
if (newWindow->surroundingWindow == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay, "Couldn't create a new window.");
}
sprintf(aWindow->interp->result, "couldn't create a new window");
goto cleanUp;
}
/* for window icon */
XStoreName(wishDisplay, newWindow->surroundingWindow, newWindow->dir);
/* Create textGc */
gcValues.foreground = aWindow->foreground;
gcValues.background = aWindow->background;
gcValues.font = newWindow->fontPtr->fid;
newWindow->textGc = XCreateGC(wishDisplay, newWindow->surroundingWindow,
GCForeground | GCBackground | GCFont, &gcValues);
/* Create reverseGc */
gcValues.foreground = aWindow->background;
gcValues.background = aWindow->selection;
gcValues.font = newWindow->fontPtr->fid;
newWindow->reverseGc = XCreateGC(wishDisplay,
newWindow->surroundingWindow,
GCForeground | GCBackground | GCFont, &gcValues);
/*
* To get a nice divider between the title/entry window and the display
* window, create the windows with no border and create a divider as
* a separate, thin, window. The title window is also a command entry
* window which is why I don't just use Sx_TitleCreate().
*/
newWindow->titleWindow = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow,
SX_TOP, Sx_DefaultHeight(wishDisplay, newWindow->titleFontPtr),
0, 0, newWindow->titleBorder, (Window) 0,
newWindow->titleBackground);
if (newWindow->titleWindow == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay, "Couldn't create title window.");
}
sprintf(aWindow->interp->result, "couldn't create title window");
goto cleanUp;
}
/* Put "title" in window. */
Sx_EntryMake(wishDisplay, newWindow->titleWindow,
newWindow->surroundingWindow, "Directory: ",
newWindow->titleFontPtr, newWindow->titleForeground,
newWindow->titleBackground, newWindow->editDir,
sizeof (newWindow->editDir));
newWindow->txOutsideWindow = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow,
SX_BOTTOM, 8 * Sx_DefaultHeight(wishDisplay, newWindow->fontPtr),
0, 0, newWindow->txBorder, (Window) 0, newWindow->txBackground);
/* Unless i can get this info from Sx, how else can I do it? */
{
Window dummy1;
int x, y, width, height, border_width, dummy2;
if (XGetGeometry(wishDisplay, newWindow->txOutsideWindow, &dummy1,
&x, &y, &width, &height, &border_width, &dummy2) == 0) {
Sx_Panic(wishDisplay, "Couldn't get tx window geometry.");
}
info.width = width;
}
/* Create first divider */
newWindow->divider1Window = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow,
SX_TOP, 1, 0, 0, newWindow->border, (Window) 0, newWindow->border);
if (newWindow->divider1Window == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay,
"Couldn't create the first border between windows.");
}
sprintf(aWindow->interp->result,
"couldn't create the first border between windows");
goto cleanUp;
}
newWindow->menuBar = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow, SX_TOP,
Sx_DefaultHeight(wishDisplay, newWindow->titleFontPtr), 0, 0,
newWindow->menuForeground, (Window) 0, newWindow->menuBackground);
/* Create next divider */
newWindow->divider2Window = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow,
SX_TOP, 1, 0, 0, newWindow->border, (Window) 0, newWindow->border);
if (newWindow->divider2Window == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay,
"Couldn't create the second border between windows.");
}
sprintf(aWindow->interp->result,
"couldn't create the second border between windows");
goto cleanUp;
}
newWindow->sortWindow = Sx_TitleCreate(wishDisplay,
newWindow->surroundingWindow,
SX_TOP, Sx_DefaultHeight(wishDisplay, newWindow->fontPtr), 0,
newWindow->fontPtr,
newWindow->sortForeground, newWindow->sortBackground,
newWindow->sortBackground, NULL, NULL, NULL);
if (newWindow->sortWindow == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay, "Couldn't create the sort window.");
}
sprintf(aWindow->interp->result, "couldn't create the sort window");
goto cleanUp;
}
newWindow->divider3Window = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow,
SX_TOP, 1, 0, 0, newWindow->border, (Window) 0, newWindow->border);
if (newWindow->divider3Window == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay,
"Couldn't create the third border between windows.");
}
sprintf(aWindow->interp->result,
"couldn't create the third border between windows");
goto cleanUp;
}
newWindow->fieldsWindow = Sx_TitleCreate(wishDisplay,
newWindow->surroundingWindow,
SX_TOP, Sx_DefaultHeight(wishDisplay, newWindow->fontPtr), 0,
newWindow->fontPtr,
newWindow->fieldsForeground, newWindow->fieldsBackground,
newWindow->fieldsBackground, NULL, NULL, NULL);
if (newWindow->fieldsWindow == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay, "Couldn't create the fields window.");
}
sprintf(aWindow->interp->result, "couldn't create fields window");
goto cleanUp;
}
/* Create next divider */
newWindow->divider4Window = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow,
SX_TOP, 1, 0, 0, newWindow->border, (Window) 0, newWindow->border);
if (newWindow->divider4Window == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay,
"Couldn't create the fourth border between windows.");
}
sprintf(aWindow->interp->result,
"couldn't create the fourth border between windows");
goto cleanUp;
}
/*
* Is 1 really the size I want for the scrollbar border?
*/
newWindow->scrollWindow = Sx_ScrollbarCreate(wishDisplay,
newWindow->surroundingWindow,
SX_RIGHT, 1, newWindow->scrollForeground,
newWindow->scrollBackground,
newWindow->scrollElevator, newWindow->border, WishScroll,
newWindow);
if (newWindow->scrollWindow == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay, "Couldn't create the scroll bar.");
}
sprintf(aWindow->interp->result, "couldn't create the scrollbar");
goto cleanUp;
}
/* Create next divider */
newWindow->divider5Window = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow, SX_RIGHT, 1, 0, 0, newWindow->border,
(Window) 0, newWindow->border);
if (newWindow->divider5Window == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay,
"Couldn't create the fifth border between windows.");
}
sprintf(aWindow->interp->result,
"couldn't create the fifth border between windows");
goto cleanUp;
}
#ifdef NOTDEF
/* what was this for in X10? */
tx_RegisterPtr = FALSE;
#endif /* NOTDEF */
info.source = NULL;
info.fontPtr = newWindow->fontPtr;
/*
* outside of tx window is 8 * Sx_DefaultHeight, but inside is more or
* less 4 times, if you count title bars, etc.
*/
info.height = 4 * Sx_DefaultHeight(wishDisplay, newWindow->fontPtr);
info.foreground = newWindow->txForeground;
info.background = newWindow->txBackground;
info.border = newWindow->txBorder;
info.sbForeground = newWindow->scrollForeground;
info.sbBackground = newWindow->scrollBackground;
info.sbElevator = newWindow->scrollElevator;
info.titleForeground = newWindow->titleForeground;
info.titleBackground = newWindow->titleBackground;
info.titleStripe = newWindow->titleForeground;
info.title = NULL;
info.flags = TX_NO_TITLE;
result = Tx_SetupAndFork(aWindow->interp, wishDisplay,
newWindow->txOutsideWindow, &info, args);
if (result != TCL_OK) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay,
"Couldn't set up Tx window.");
}
sprintf(aWindow->interp->result,
"couldn't set up Tx window");
goto cleanUp;
}
/* Create next divider */
newWindow->divider6Window = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow,
SX_BOTTOM, 1, 0, 0, newWindow->border, (Window) 0,
newWindow->border);
if (newWindow->divider6Window == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay,
"Couldn't create the sixth border between windows.");
}
sprintf(aWindow->interp->result,
"couldn't create the sixth border between windows");
goto cleanUp;
}
/* Create display subwindow */
newWindow->displayWindow = Sx_CreatePacked(wishDisplay,
newWindow->surroundingWindow,
SX_TOP, 0, 1, 0, newWindow->border, (Window) 0,
newWindow->background);
if (newWindow->displayWindow == 0) {
if (aWindow->interp == NULL) {
Sx_Panic(wishDisplay, "Couldn't create the display window.");
}
sprintf(aWindow->interp->result, "couldn't create display window");
cleanUp:
if (newWindow->surroundingWindow != NULL) {
XDestroySubwindows(wishDisplay, newWindow->surroundingWindow);
XDestroyWindow(wishDisplay, newWindow->surroundingWindow);
}
free(newWindow);
return NULL;
}
/*
* Increment the window reference count and enter the window information
* structure into the wishWindowContext.
*/
wishWindowCount++;
XSaveContext(wishDisplay, newWindow->surroundingWindow,
(caddr_t) wishWindowContext, newWindow);
/*
* Start up the display with newWindow->dir as the directory of the display.
* WishInit() will map the surrounding window. It may first change
* its size.
*/
WishInit(newWindow);
newWindow->firstElement = 1; /* start displaying from beginning */
/*
* WishSetPositions() and WishRedraw() will be called as a result
* of the handlers, since Sx stuff generates an ExposureMask event.
* This means I don't need to call them here explicitly.
*/
/* For the handlers, should I pass the window or newWindow as clientData? */
Sx_HandlerCreate(wishDisplay, newWindow->surroundingWindow,
EnterWindowMask, WishHandleEnterEvent, newWindow);
/*
* Select these button events in the display window, but pass the
* surrounding window to the handlers.
*/
Sx_HandlerCreate(wishDisplay, newWindow->displayWindow, ButtonPressMask
| PointerMotionMask | LeaveWindowMask, WishMouseEvent,
newWindow->surroundingWindow);
/*
* Select these key press events in the title subwindow, but
* pass the surrounding window to the handlers.
*/
Sx_HandlerCreate(wishDisplay, newWindow->titleWindow, KeyPressMask,
WishEditDir, newWindow->surroundingWindow);
/*
* Move this further up before various datastructures are created?
* Add dir to wish's list. Use windowID to match this dir for this
* window.
*/
if (!MonClient_AddDir(newWindow->dir, newWindow->surroundingWindow)) {
/* What should I do here? */
Sx_Panic(wishDisplay,
"File system monitor failed in WishCreate().");
}
return newWindow;
}
/*
*----------------------------------------------------------------------
*
* WishInit --
*
* Initialize a new flat display.
*
* Results:
* None.
*
* Side effects:
* Lots.
*
*----------------------------------------------------------------------
*/
void
WishInit(aWindow)
WishWindow *aWindow; /* info for this instance of display */
{
XColor cursorForeground;
XColor cursorBackground;
Pixmap source;
cursorForeground.pixel = aWindow->background;
cursorBackground.pixel = aWindow->foreground;
XQueryColor(wishDisplay, DefaultColormap(wishDisplay,
DefaultScreen(wishDisplay)), &cursorForeground);
XQueryColor(wishDisplay, DefaultColormap(wishDisplay,
DefaultScreen(wishDisplay)), &cursorBackground);
if (flatCursor == -1) {
source = XCreateBitmapFromData(wishDisplay,
DefaultRootWindow(wishDisplay), flatCursor_bits,
flatCursor_width, flatCursor_height);
flatCursor = XCreatePixmapCursor(wishDisplay, source, None,
&cursorBackground, &cursorForeground, flatCursor_x_hot,
flatCursor_y_hot);
XFreePixmap(wishDisplay, source);
}
/* We'll need the cursor later - don't free it */
XDefineCursor(wishDisplay, aWindow->displayWindow, flatCursor);
/*
* When work is being done, the cursor changes to the "wait" cursor.
*/
if (waitCursor == -1) {
source = XCreateBitmapFromData(wishDisplay,
DefaultRootWindow(wishDisplay), waitCursor_bits,
waitCursor_width, waitCursor_height);
waitCursor = XCreatePixmapCursor(wishDisplay, source, None,
&cursorBackground, &cursorForeground, waitCursor_x_hot,
waitCursor_y_hot);
XFreePixmap(wishDisplay, source);
}
{
Window dummy1;
int x, y, width, height, border_width, dummy2;
if (XGetGeometry(wishDisplay, aWindow->displayWindow, &dummy1,
&x, &y, &width, &height, &border_width, &dummy2) == 0) {
Sx_Panic(wishDisplay, "Couldn't get display window geometry.");
}
WishSetWindowAndRowInfo(aWindow, height, width);
}
/* initialize data structures */
aWindow->displayInstructions = 0;
aWindow->sortingInstructions = 0;
aWindow->maxNameLength = 0; /* longest length name */
aWindow->maxEntryWidth = 0; /* longest entry */
aWindow->numElements = -1; /* >= 0 means already initialized */
aWindow->totalDisplayEntries = 0;
/* numRows and rowHeight set above */
aWindow->firstElement = aWindow->lastElement = -1;
/* 8 columns is probably more than plenty to start out with. */
aWindow->columns = (WishColumn *) malloc(8 * sizeof (WishColumn));
aWindow->maxColumns = 8;
aWindow->usedCol = -1;
if (wishResizeP) {
aWindow->resizeP = TRUE;
} else {
aWindow->resizeP = FALSE;
}
if (wishPickSizeP) {
aWindow->pickSizeP = TRUE;
} else {
aWindow->pickSizeP = FALSE;
}
if (wishShowEmptyGroupsP) {
aWindow->hideEmptyGroupsP = FALSE;
} else {
aWindow->hideEmptyGroupsP = TRUE;
}
aWindow->groupList = NULL;
aWindow->selectionList = NULL;
/* create command bindings table and tcl interpreter. */
WishCmdTableInit(&(aWindow->cmdTable), &(aWindow->interp),
commands, (ClientData) aWindow);
WishSourceConfig(aWindow);
/* figure initial size */
if (aWindow->pickSizeP) {
aWindow->pickSizeP = FALSE; /* only the first time */
/* This next will cause the surrounding window to change shape */
FigureWindowSize(aWindow, GetMaxEntryWidth(aWindow));
}
/* map surrounding window */
XMapWindow(wishDisplay, aWindow->surroundingWindow);
Sx_HandlerCreate(wishDisplay, aWindow->displayWindow,
ExposureMask | StructureNotifyMask,
WishHandleDrawingEvent, (ClientData) aWindow);
Sx_HandlerCreate(wishDisplay, aWindow->displayWindow, KeyPressMask,
WishKeyProc, (ClientData) aWindow);
Sx_HandlerCreate(wishDisplay, aWindow->menuBar, EnterWindowMask,
WishMenuEntryProc, (ClientData) aWindow);
return;
}
/*
*----------------------------------------------------------------------
*
* WishSetPositions --
*
* Figure out and set the coordinates of things to display.
* This means sticking things in columns and determining when
* the display would be filled up.
*
* Results:
* None.
*
* Side effects:
* The coordinates change. A new column or so may be allocated.
*
*----------------------------------------------------------------------
*/
void
WishSetPositions(aWindow)
WishWindow *aWindow;
{
WishGroup *tmpGroupPtr = NULL;
WishFile *tmpFilePtr = NULL;
WishColumn *newColumns;
Boolean spaceP = FALSE;
int numCols;
int i;
int maxEntryWidth;
int numMappedHeaders = 0; /* Use at end for ignoring
* extra expose events. */
#ifdef SCROLL_DEBUG
fprintf(stderr, "Entered WishSetPositions:\n");
fprintf(stderr, "\tfirstElement is %d\n",
aWindow->firstElement);
fprintf(stderr, "\tlastElement is %d\n",
aWindow->lastElement);
fprintf(stderr, "\tnumElements is %d\n",
aWindow->numElements);
fprintf(stderr, "\tcolumns used is %d\n",
aWindow->usedCol + 1);
#endif SCROLL_DEBUG
if (aWindow->notifierP) {
return;
}
if (aWindow->firstElement <= 0) {
sprintf(wishErrorMsg,
"Entered WishSetPositions with firstElement = %d",
aWindow->firstElement);
Sx_Panic(wishDisplay, wishErrorMsg);
}
/*
* Avoid exposure events from creating and resizing windows below. The
* window will be remapped later causing WishRedraw() to be called.
*/
XUnmapWindow(wishDisplay, aWindow->displayWindow);
maxEntryWidth = GetMaxEntryWidth(aWindow);
if (aWindow->resizeP) {
FigureWindowSize(aWindow, maxEntryWidth);
}
GetColumnWidthInfo(aWindow, maxEntryWidth, &(aWindow->columnWidth),
&numCols);
#ifdef SCROLL_DEBUG
fprintf(stderr, "Number of columns to use is %d\n", numCols);
#endif SCROLL_DEBUG
/* do we need to allocate more columns? */
if (numCols > aWindow->maxColumns) {
newColumns = (WishColumn *)
malloc(aWindow->maxColumns * 2 * sizeof (WishColumn));
for (i = 0; i < aWindow->maxColumns; i++) {
newColumns[i] = aWindow->columns[i];
}
free(aWindow->columns);
aWindow->columns = newColumns;
aWindow->maxColumns *= 2;
}
/* get to the first one to display */
i = 0;
aWindow->lastElement = 0;
for (tmpGroupPtr = aWindow->groupList; tmpGroupPtr != NULL;
tmpGroupPtr = tmpGroupPtr->nextPtr) {
/*
* Check if we've hit the right element to start displaying at. If
* so, then check that either it's okay to display headers for empty
* groups, or else this isn't an empty group.
*/
if ((i + 1 == aWindow->firstElement) && (!aWindow->hideEmptyGroupsP ||
tmpGroupPtr->fileList != NULL)) {
break;
}
tmpGroupPtr->myColumn = -1;
tmpGroupPtr->x = tmpGroupPtr->y = -1;
if (tmpGroupPtr->headerWindow != UNINITIALIZED) {
XUnmapWindow(wishDisplay, tmpGroupPtr->headerWindow);
}
/* only increment if this was a visible header */
if (!aWindow->hideEmptyGroupsP || tmpGroupPtr->fileList != NULL) {
i++;
}
for (tmpFilePtr = tmpGroupPtr->fileList; tmpFilePtr != NULL;
tmpFilePtr = tmpFilePtr->nextPtr) {
if (i + 1 == aWindow->firstElement) {
break;
} else {
tmpFilePtr->x = tmpFilePtr->y = -1;
tmpFilePtr->myColumn = -1;
}
i++;
}
if (tmpFilePtr != NULL) {
break; /* we found it */
}
if (i+1 == aWindow->firstElement) {
/*
* The next thing we would display is a space followed by a
* group header, unless the group is an empty group and we aren't
* supposed to be displaying empty groups...
*/
if (!aWindow->hideEmptyGroupsP || (tmpGroupPtr->nextPtr != NULL &&
tmpGroupPtr->nextPtr->fileList != NULL)) {
spaceP = TRUE;
tmpGroupPtr = tmpGroupPtr->nextPtr;
break;
}
}
/* only increment if this would be a space after a visible header */
if (!aWindow->hideEmptyGroupsP || tmpGroupPtr->fileList != NULL) {
i++;
}
}
if (tmpGroupPtr == NULL) { /* all groups were empty, no display */
goto finished;
}
/* We've figured out what to start displaying */
/* Now fill in the columns */
for (aWindow->usedCol = 0; aWindow->usedCol < numCols; aWindow->usedCol++) {
aWindow->columns[aWindow->usedCol].x =
aWindow->usedCol * aWindow->columnWidth;
for (i = 0; i < aWindow->numRows; i++) {
if (spaceP == TRUE) {
spaceP = FALSE;
continue;
}
/*
* If tmpFilePtr is NULL, we have come to a new group header.
*/
if (tmpFilePtr == NULL) {
/* set tmpFilePtr to fileList for this group. */
tmpFilePtr = tmpGroupPtr->fileList;
if (aWindow->hideEmptyGroupsP && tmpFilePtr == NULL) {
if (tmpGroupPtr->headerWindow != UNINITIALIZED) {
XUnmapWindow(wishDisplay, tmpGroupPtr->headerWindow);
}
tmpGroupPtr = tmpGroupPtr->nextPtr;
i--; /* so that i is the same next iteration */
if (tmpGroupPtr == NULL) { /* end of groups */
goto finished;
}
continue;
}
tmpGroupPtr->myColumn = aWindow->usedCol;
tmpGroupPtr->x = aWindow->columns[aWindow->usedCol].x;
tmpGroupPtr->y = i * aWindow->rowHeight;
strcpy(tmpGroupPtr->editHeader, tmpGroupPtr->rule);
if (tmpGroupPtr->headerWindow == UNINITIALIZED) {
/* Need to create a header window */
/* necessary? */ tmpGroupPtr->entry_width = aWindow->columnWidth;
tmpGroupPtr->entry_x = tmpGroupPtr->x;
tmpGroupPtr->entry_y = tmpGroupPtr->y;
/*
* If it's the first column, then start it one pixel
* to the left, so that borders overlap.
*/
if (tmpGroupPtr->myColumn > 0) {
tmpGroupPtr->headerWindow =
Sx_EntryCreate(wishDisplay,
aWindow->displayWindow,
aWindow->displayWindow,
tmpGroupPtr->x, tmpGroupPtr->y - 1,
aWindow->columnWidth - 1,
aWindow->rowHeight - 1, 1, NULL,
aWindow->fontPtr, aWindow->entryForeground,
aWindow->entryBackground,
tmpGroupPtr->editHeader,
sizeof (tmpGroupPtr->editHeader));
} else {
tmpGroupPtr->headerWindow =
Sx_EntryCreate(wishDisplay,
aWindow->displayWindow,
aWindow->displayWindow,
tmpGroupPtr->x - 1, tmpGroupPtr->y - 1,
aWindow->columnWidth,
aWindow->rowHeight - 1, 1, NULL,
aWindow->fontPtr, aWindow->entryForeground,
aWindow->entryBackground,
tmpGroupPtr->editHeader,
sizeof (tmpGroupPtr->editHeader));
}
if (tmpGroupPtr->headerWindow == 0) {
Sx_Panic(wishDisplay,
"You've run out of windows?! Farewell!");
}
XSaveContext(wishDisplay, tmpGroupPtr->headerWindow,
wishWindowContext, (caddr_t) aWindow);
XSaveContext(wishDisplay, tmpGroupPtr->headerWindow,
wishGroupWindowContext, (caddr_t) tmpGroupPtr);
fprintf(stderr, "WishEditRule set as handler, hdr wind. is %d\n", tmpGroupPtr->headerWindow);
Sx_HandlerCreate(wishDisplay,
tmpGroupPtr->headerWindow, KeyPressMask,
WishEditRule, tmpGroupPtr->headerWindow);
} else {
/* is the window in a new place? */
if (tmpGroupPtr->entry_x != tmpGroupPtr->x ||
tmpGroupPtr->entry_y != tmpGroupPtr->y ||
tmpGroupPtr->entry_width !=
aWindow->columnWidth) {
XWindowChanges changes;
tmpGroupPtr->entry_x = tmpGroupPtr->x;
tmpGroupPtr->entry_y = tmpGroupPtr->y;
tmpGroupPtr->entry_width = aWindow->columnWidth;
if (tmpGroupPtr->myColumn > 0) {
changes.x = tmpGroupPtr->x;
changes.y = tmpGroupPtr->y - 1;
changes.width = aWindow->columnWidth - 1;
changes.height = aWindow->rowHeight - 1;
} else {
changes.x = tmpGroupPtr->x - 1;
changes.y = tmpGroupPtr->y - 1;
changes.width = aWindow->columnWidth;
changes.height = aWindow->rowHeight - 1;
}
XConfigureWindow(wishDisplay,
tmpGroupPtr->headerWindow,
CWX | CWY | CWWidth | CWHeight, &changes);
}
}
/* in case it wasn't visible last time */
XMapWindow(wishDisplay, tmpGroupPtr->headerWindow);
numMappedHeaders++; /* another header window mapped */
/*
* If fileList is NULL for this group, move to next group.
* If this new group isn't null, it means we need another space.
* Otherwise, we're finished with all the groups.
*/
if (tmpFilePtr != NULL) {
continue;
}
/*
* The group's fileList is null, move on to new group.
* We can only get here with a null fileList if
* aWindow->hideEmptyGroupsP is FALSE.
*/
tmpGroupPtr = tmpGroupPtr->nextPtr;
if (tmpGroupPtr == NULL) {
/* end of groups */
aWindow->lastElement = i + 1;
break;
}
/* leave tmpFilePtr NULL so that we know we're between groups */
spaceP = TRUE;
continue;
}
/* tmpFilePtr was not NULL, so set positions for the file name. */
tmpFilePtr->x = aWindow->columns[aWindow->usedCol].x;
tmpFilePtr->y = i * aWindow->rowHeight;
tmpFilePtr->myColumn = aWindow->usedCol;
/* move on to next file */
tmpFilePtr = tmpFilePtr->nextPtr;
if (tmpFilePtr == NULL) {
/* end of group */
tmpGroupPtr = tmpGroupPtr->nextPtr;
if (tmpGroupPtr == NULL) {
/* end of groups */
aWindow->lastElement = i + 1;
break;
}
spaceP = TRUE;
}
continue;
}
/* We're at the end of a column */
if (tmpGroupPtr == NULL) {
/* end of groups */
aWindow->usedCol++; /* so it ends one bigger than used */
break;
}
}
aWindow->usedCol--; /* loop leaves it one too big */
finished:
/* mark the rest as not visible */
for ( ; tmpGroupPtr != NULL; tmpGroupPtr = tmpGroupPtr->nextPtr) {
/* If we stopped at a header, mark it as not visible */
if (tmpFilePtr == NULL) {
tmpGroupPtr->myColumn = -1;
tmpGroupPtr->x = tmpGroupPtr->y = -1;
if (tmpGroupPtr->headerWindow != UNINITIALIZED) {
XUnmapWindow(wishDisplay, tmpGroupPtr->headerWindow);
}
tmpFilePtr = tmpGroupPtr->fileList;
}
for ( ; tmpFilePtr != NULL; tmpFilePtr = tmpFilePtr->nextPtr) {
tmpFilePtr->x = tmpFilePtr->y = -1;
tmpFilePtr->myColumn = -1;
}
}
/* The number of the last element visible -- includes spaces and headers */
if (aWindow->lastElement == 0) {
aWindow->lastElement = aWindow->firstElement - 1 +
((aWindow->usedCol + 1) * aWindow->numRows);
} else {
/* We're partway into a column, add on columns up to this one */
aWindow->lastElement += aWindow->firstElement - 1 +
(aWindow->usedCol * aWindow->numRows);
}
/* Get rid of extraneous redraw events from mapping(?) Sx entry windows. */
for (i = 0; i < numMappedHeaders; i++) {
XEvent tossEvent; /* dispose of this extra event */
XCheckWindowEvent(wishDisplay, aWindow->displayWindow, ExposureMask,
&tossEvent);
}
/* This causes WishRedraw() to be called, so the whole thing appears. */
XMapWindow(wishDisplay, aWindow->displayWindow);
#ifdef SCROLL_DEBUG
fprintf(stderr, "At end of WishSetPositions:\n");
fprintf(stderr, "\tfirstElement is %d\n",
aWindow->firstElement);
fprintf(stderr, "\tlastElement is %d\n",
aWindow->lastElement);
fprintf(stderr, "\tnumElements is %d\n",
aWindow->numElements);
fprintf(stderr, "\tnumGroups is %d\n", aWindow->numGroups);
fprintf(stderr, "\tnumRows is %d\n", aWindow->numRows);
fprintf(stderr, "\tcolumns used is %d\n",
aWindow->usedCol + 1);
#endif SCROLL_DEBUG
return;
}
/*
*----------------------------------------------------------------------
*
* WishRedraw --
*
* Redraw display with positions already set.
*
* Results:
* None.
*
* Side effects:
* The display is redrawn.
*
*----------------------------------------------------------------------
*/
void
WishRedraw(aWindow)
WishWindow *aWindow;
{
int i;
WishGroup *tmpGroupPtr = NULL;
WishFile *tmpPtr = NULL;
float top, bottom;
char fields[MAXNAMLEN + (3 * 26) + 11]; /* space allocation
* described below */
char sorting[50];
Boolean somethingDrawnP = FALSE;
if (aWindow->notifierP) {
return;
}
strcpy(fields, "Filename");
for (i = 0; i < aWindow->maxNameLength - strlen("Filename"); i++) {
/* Very wasteful... */
strcat(fields, " ");
}
if (aWindow->displayInstructions & WISH_ATIME_FIELD) {
/* 24 chars needed for time, plus 2 spaces == 26 */
strcat(fields, " AccessTime ");
}
if (aWindow->displayInstructions & WISH_MTIME_FIELD) {
/* 24 chars needed for time, plus 2 spaces == 26 */
strcat(fields, " DataModifyTime ");
}
if (aWindow->displayInstructions & WISH_DTIME_FIELD) {
/* 24 chars needed for time, plus 2 spaces == 26 */
/*
* This is one of the few places where Descriptor isn't spelled out -
* for space considerations.
*/
strcat(fields, " DescModifyTime ");
}
if (aWindow->displayInstructions & WISH_SIZE_FIELD) {
/* 9 chars needed for size, plus 2 spaces == 11 */
strcat(fields, " Bytes");
}
strcpy(sorting, "Sorted by: ");
if (aWindow->sortingInstructions & WISH_ALPHA_SORT) {
if (aWindow->sortingInstructions & WISH_REVERSE_SORT) {
strcat(sorting, "Reverse Alphabet");
} else {
strcat(sorting, "Alphabet"); }
}
if (aWindow->sortingInstructions & WISH_ATIME_SORT) {
if (aWindow->sortingInstructions & WISH_REVERSE_SORT) {
strcat(sorting, "Reverse AccessTime");
} else {
strcat(sorting, "AccessTime");
}
}
if (aWindow->sortingInstructions & WISH_MTIME_SORT) {
if (aWindow->sortingInstructions & WISH_REVERSE_SORT) {
strcat(sorting, "Reverse DataModifyTime");
} else {
strcat(sorting, "DataModifyTime");
}
}
if (aWindow->sortingInstructions & WISH_DTIME_SORT) {
if (aWindow->sortingInstructions & WISH_REVERSE_SORT) {
strcat(sorting, "Reverse DescriptorModifyTime");
} else {
strcat(sorting, "DescriptorModifyTime");
}
}
if (aWindow->sortingInstructions & WISH_SIZE_SORT) {
if (aWindow->sortingInstructions & WISH_REVERSE_SORT) {
strcat(sorting, "Reverse Size");
} else {
strcat(sorting, "Size");
}
}
#ifdef SCROLL_DEBUG
fprintf(stderr, "Entered WishRedraw:\n");
fprintf(stderr, "\tfirstElement is %d\n",
aWindow->firstElement);
fprintf(stderr, "\tlastElement is %d\n",
aWindow->lastElement);
fprintf(stderr, "\tnumElements is %d\n",
aWindow->numElements);
fprintf(stderr, "\tnumGroups is %d\n", aWindow->numGroups);
#endif SCROLL_DEBUG
XClearArea(wishDisplay, aWindow->displayWindow, 0, 0, 0, 0, False);
for (tmpGroupPtr = aWindow->groupList;
tmpGroupPtr != NULL; tmpGroupPtr = tmpGroupPtr->nextPtr) {
for (tmpPtr = tmpGroupPtr->fileList;
tmpPtr != NULL; tmpPtr = tmpPtr->nextPtr) {
WishRedrawFile(aWindow, tmpPtr);
somethingDrawnP = TRUE;
}
}
/*
* Now draw the column dividers.
*/
if (somethingDrawnP) {
for (i = 1; i <= aWindow->usedCol; i++) {
XDrawLine(wishDisplay, aWindow->displayWindow,
aWindow->textGc,
aWindow->columns[i].x, 0,
aWindow->columns[i].x, aWindow->windowHeight);
}
}
/*
* Now set the scroll bar to match what will be displayed.
*/
if (aWindow->numRows == 0) {
top = 0.0;
bottom = 1.0;
} else {
/*
* First (last) entry divided by number of entries required. (This
* includes any displayed spaces and groups.)
*/
top = ((float) aWindow->firstElement - 1) /
((float) aWindow->totalDisplayEntries);
bottom = ((float) aWindow->lastElement) /
((float) aWindow->totalDisplayEntries);
}
#ifdef SCROLL_DEBUG
fprintf(stderr, "At end of WishRedraw:\n");
fprintf(stderr, "\ttop is %f\n", top);
fprintf(stderr, "\tbottom is %f\n", bottom);
fprintf(stderr, "\tcalling SetRange.\n");
#endif SCROLL_DEBUG
Sx_ScrollbarSetRange(wishDisplay, aWindow->scrollWindow, top, bottom);
Sx_TitleMake(wishDisplay, aWindow->sortWindow, aWindow->fontPtr,
aWindow->sortForeground, aWindow->sortBackground,
aWindow->sortBackground, sorting, NULL, NULL);
Sx_TitleMake(wishDisplay, aWindow->fieldsWindow, aWindow->fontPtr,
aWindow->fieldsForeground, aWindow->fieldsBackground,
aWindow->fieldsBackground, fields, NULL, NULL);
return;
}
/*
*----------------------------------------------------------------------
*
* WishRedrawFile --
*
* Redraw a file entry. Highlight with a box, or indicate that it is
* selected, if required.
*
* Results:
* None.
*
* Side effects:
* The file entry is redisplayed.
*
*----------------------------------------------------------------------
*/
void
WishRedrawFile(aWindow, filePtr)
WishWindow *aWindow;
WishFile *filePtr;
{
char *space = NULL;
int secondFieldStart;
int ascent;
int lbearing; /* to indent string enough that we don't
* draw a box over its first char */
if (aWindow->notifierP) {
return;
}
if (filePtr->x == -1) { /* is it visible? */
return;
}
ascent = aWindow->fontPtr->ascent;
lbearing = -4;
if ((aWindow->displayInstructions & ~WISH_NAME_FIELD) != 0) {
space = (char *) malloc(aWindow->maxEntryWidth + 1 -
aWindow->maxNameLength);
space[0] = '\0';
WishGetFileFields(aWindow, filePtr, &space);
}
secondFieldStart =
WISH_CHAR_TO_WIDTH(aWindow->maxNameLength + 2, aWindow->fontPtr);
if (filePtr->selectedP || filePtr->myGroupPtr->selectedP) {
/* should highlight */
XDrawImageString(wishDisplay, aWindow->displayWindow,
aWindow->reverseGc, filePtr->x + -lbearing + 1,
filePtr->y + ascent, filePtr->name, strlen(filePtr->name));
if (space != NULL) {
if (filePtr->lineP) {
XDrawImageString(wishDisplay, aWindow->displayWindow,
aWindow->reverseGc,
filePtr->x + secondFieldStart,
filePtr->y + ascent, space, strlen(space));
} else {
XDrawImageString(wishDisplay, aWindow->displayWindow,
aWindow->textGc,
filePtr->x + secondFieldStart,
filePtr->y + ascent, space, strlen(space));
}
}
} else {
XDrawImageString(wishDisplay, aWindow->displayWindow, aWindow->textGc,
filePtr->x + -lbearing + 1, filePtr->y + ascent, filePtr->name,
strlen(filePtr->name));
if (space != NULL) {
XDrawImageString(wishDisplay, aWindow->displayWindow,
aWindow->textGc, filePtr->x + secondFieldStart,
filePtr->y + ascent, space, strlen(space));
}
}
/* draw or undraw a box around it */
{
XPoint vlist[5];
vlist[0].x = filePtr->x + 1;
vlist[0].y = filePtr->y + aWindow->rowHeight;
/*
* To make up for indentation of string by -lbearing amount.
*/
vlist[1].x = -lbearing +
WISH_CHAR_TO_WIDTH(aWindow->maxNameLength, aWindow->fontPtr);
vlist[1].y = 0;
vlist[2].x = 0;
vlist[2].y = -(aWindow->rowHeight);
vlist[3].x = -(vlist[1].x);
vlist[3].y = 0;
/* should be equal to first point - if not, make all rel. to origin. */
vlist[4].x = 0;
vlist[4].y = -(vlist[2].y);
if (filePtr->highlightP) {
/* should be selectionGc */
XDrawLines(wishDisplay, aWindow->displayWindow,
aWindow->textGc, vlist, 5, CoordModePrevious);
} else {
XDrawLines(wishDisplay, aWindow->displayWindow,
aWindow->reverseGc, vlist, 5, CoordModePrevious);
}
}
if (space != NULL) {
free(space);
}
return;
}
/*
*----------------------------------------------------------------------
*
* WishGetFileFields --
*
* Get the additional fields to display for a file entry beyond the
* file name.
* If *buf is null, then allocate space for the string to return.
* Otherwise copy the return value into *buf.
*
* Results:
* None.
*
* Side effects:
* The file entry is redisplayed.
*
*----------------------------------------------------------------------
*/
void
WishGetFileFields(aWindow, filePtr, buf)
WishWindow *aWindow;
WishFile *filePtr;
char **buf;
{
char timeBuf[26]; /* 26 chars according to ctime man page */
char intBuf[CVT_INT_BUF_SIZE + 1]; /* const defined in my .h file */
int i;
char *space;
/* What to do here? */
if (*buf == NULL) {
*buf = (char *) malloc(aWindow->maxEntryWidth + 1 -
aWindow->maxNameLength);
*buf[0] = '\0';
}
space = *buf;
/* Any fields except for name? */
if (!(aWindow->displayInstructions & (~WISH_NAME_FIELD))) {
/* Could free up space from attrPtr field here, if I want. */
return;
}
if (filePtr->attrPtr == NULL) {
filePtr->attrPtr = (struct stat *) malloc(sizeof (struct stat));
if (lstat(filePtr->name, filePtr->attrPtr) != 0) {
sprintf(wishErrorMsg, "%s %s. %s.",
"Couldn't get attributes for file",
filePtr->name, "The file may no longer exist");
aWindow->notifierP = TRUE;
Sx_Notify(wishDisplay, aWindow->surroundingWindow, -1, -1, 0,
wishErrorMsg, NULL, TRUE, "Continue",
(char *) NULL);
aWindow->notifierP = FALSE;
bzero(filePtr->attrPtr, sizeof (struct stat));
strcat(space, " X ");
return;
}
}
if (aWindow->displayInstructions & WISH_ATIME_FIELD) {
/* 24 chars needed for time, plus 2 spaces == 26 */
strcpy(timeBuf, ctime(&(filePtr->attrPtr->st_atime)));
/* wasteful to do twice, I suppose */
if (index(timeBuf, '\n') != NULL) {
*(index(timeBuf, '\n')) = '\0';
}
strcat(space, timeBuf);
strcat(space, " ");
}
if (aWindow->displayInstructions & WISH_MTIME_FIELD) {
/* 24 chars needed for time, plus 2 spaces */
strcpy(timeBuf, ctime(&(filePtr->attrPtr->st_mtime)));
/* wasteful to do twice, I suppose */
if (index(timeBuf, '\n') != NULL) {
*(index(timeBuf, '\n')) = '\0';
}
strcat(space, timeBuf);
strcat(space, " ");
}
if (aWindow->displayInstructions & WISH_DTIME_FIELD) {
/* 24 chars needed for time, plus 2 spaces */
strcpy(timeBuf, ctime(&(filePtr->attrPtr->st_ctime)));
/* wasteful to do twice, I suppose */
if (index(timeBuf, '\n') != NULL) {
*(index(timeBuf, '\n')) = '\0';
}
strcat(space, timeBuf);
strcat(space, " ");
}
if (aWindow->displayInstructions & WISH_SIZE_FIELD) {
/* 9 chars needed for size, plus 2 spaces */
sprintf(intBuf, "%d", filePtr->attrPtr->st_size);
for (i = 0; i < 9 - strlen(intBuf); i++) {
strcat(space, " ");
}
strcat(space, intBuf);
strcat(space, " ");
}
#ifdef NOTDEF
if (aWindow->displayInstructions & WISH_OTHERSTUFF_FIELD) {
/* 9 chars needed for size, plus 2 spaces */
}
#endif NOTDEF
return;
}
/*
*----------------------------------------------------------------------
*
* WishSetWindowAndRowInfo --
*
* Given the dimensions of the window, calculate
* the height of rows and the number of usable rows in the window,
* and set these fields (and the window dimension fields) in the
* given WishWindow structure. The row height calculation is
* made relative to the current font height specified in the fontPtr
* field of the WishWindow structure.
*
* Results:
* None.
*
* Side effects:
* The fields in the WishWindow structure that are set are
* the rowHeight, numRows, windowHeight and windowWidth fields.
*
*----------------------------------------------------------------------
*/
void
WishSetWindowAndRowInfo(aWindow, height, width)
WishWindow *aWindow;
int height, width;
{
aWindow->windowHeight = height;
aWindow->windowWidth = width;
aWindow->rowHeight = aWindow->fontPtr->max_bounds.ascent +
aWindow->fontPtr->max_bounds.descent + WISH_ROW_SPACING;
aWindow->numRows = aWindow->windowHeight / aWindow->rowHeight;
return;
}
/*
*----------------------------------------------------------------------
*
* WishRedrawGroup --
*
* Not yet implemented.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
/*ARGSUSED*/
void
WishRedrawGroup(aWindow, groupPtr)
WishWindow *aWindow;
WishGroup *groupPtr;
{
return;
}
/*
*----------------------------------------------------------------------
*
* WishMapCoordsToFile --
*
* Map the given coordinates to a file entry. The mapping will work
* if the cursor is on the same line as a file entry. It does not
* have to be directory over the file entry.
*
* Results:
* A pointer to the appropriate file entry, or NULL if there isn't
* one under the given coordinates.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
WishFile *
WishMapCoordsToFile(aWindow, x, y)
WishWindow *aWindow;
int x, y;
{
WishGroup *groupPtr;
WishFile *filePtr;
int ascent;
ascent = aWindow->fontPtr->ascent;
for (groupPtr = aWindow->groupList; groupPtr != NULL;
groupPtr = groupPtr->nextPtr) {
for (filePtr = groupPtr->fileList; filePtr != NULL;
filePtr = filePtr->nextPtr) {
if (filePtr->x == -1) { /* off the display */
continue;
}
if ((filePtr->x <= x && x <= filePtr->x + aWindow->columnWidth) &&
(filePtr->y + ascent <= y && y <= filePtr->y + ascent +
aWindow->rowHeight)) {
return filePtr;
}
}
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* WishMapCoordsToGroup --
*
* Map the given coordinates to a group header.
*
* Results:
* A pointer to the appropriate group header, or NULL if there isn't
* one under the given coordinates.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
WishGroup *
WishMapCoordsToGroup(aWindow, x, y)
WishWindow *aWindow;
int x, y;
{
WishGroup *groupPtr;
for (groupPtr = aWindow->groupList; groupPtr != NULL;
groupPtr = groupPtr->nextPtr) {
if ((groupPtr->x <= x && x <= groupPtr->x + groupPtr->length) &&
(groupPtr->y <= y && y <= groupPtr->y + aWindow->rowHeight)) {
return groupPtr;
}
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* GetMaxEntryWidth --
*
* Find the length of the longest column entry.
*
* Results:
* The length.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
GetMaxEntryWidth(aWindow)
WishWindow *aWindow;
{
WishGroup *tmpGroupPtr;
WishFile *tmpFilePtr;
Boolean getAttrsP = FALSE;
int charLength = 0;
int lbearing;
if ((aWindow->displayInstructions & ~WISH_NAME_FIELD) != 0) {
getAttrsP = TRUE;
}
lbearing = -4;
aWindow->maxNameLength = 0;
/*
* Warning: this allocates space width for the rules, even if they
* are hidden groups.
*/
for (tmpGroupPtr = aWindow->groupList; tmpGroupPtr != NULL;
tmpGroupPtr = tmpGroupPtr->nextPtr) {
charLength = strlen(tmpGroupPtr->rule);
tmpGroupPtr->length =
XTextWidth(aWindow->fontPtr, tmpGroupPtr->rule, charLength);
if (charLength > aWindow->maxNameLength) {
aWindow->maxNameLength = charLength;
}
for (tmpFilePtr = tmpGroupPtr->fileList; tmpFilePtr != NULL;
tmpFilePtr = tmpFilePtr->nextPtr) {
charLength = strlen(tmpFilePtr->name);
tmpFilePtr->length =
XTextWidth(aWindow->fontPtr, tmpFilePtr->name, charLength);
if (charLength > aWindow->maxNameLength) {
aWindow->maxNameLength = charLength;
}
}
}
aWindow->maxEntryWidth = aWindow->maxNameLength;
/* 2 chars for spaces */
aWindow->maxEntryWidth += 2;
if (getAttrsP) {
if (aWindow->displayInstructions & WISH_ATIME_FIELD) {
/* 24 chars needed for time, plus 2 spaces */
aWindow->maxEntryWidth += 26;
}
if (aWindow->displayInstructions & WISH_MTIME_FIELD) {
/* 24 chars needed for time, plus two spaces */
aWindow->maxEntryWidth += 26;
}
if (aWindow->displayInstructions & WISH_DTIME_FIELD) {
/* 24 chars needed for time, plus two spaces */
aWindow->maxEntryWidth += 26;
}
if (aWindow->displayInstructions & WISH_SIZE_FIELD) {
/* 9 chars needed for time, plus two spaces */
aWindow->maxEntryWidth += 11;
}
#ifdef NOTDEF
/* what to do about owner sizes, groups, plus perm. display? */
if (aWindow->displayInstructions & WISH_PERM_FIELD) {
/* 1 chars needed for time, plus two spaces */
aWindow->maxEntryWidth += 12;
}
if (aWindow->displayInstructions & WISH_TYPE_FIELD) {
/* 1 chars needed for time, plus two spaces */
aWindow->maxEntryWidth += 12;
}
#endif NOTDEF
}
/*
* Plus lbearing cause we want to indent string enough that we don't draw
* a box around it.
*/
return (-lbearing +
WISH_CHAR_TO_WIDTH(aWindow->maxEntryWidth, aWindow->fontPtr));
}
/*
*----------------------------------------------------------------------
*
* GetColumnWidthInfo --
*
* Figure out the best fixed column width. This includes the
* extra WISH_COLUMN_SPACING added. Also figure out the number
* of columns.
*
* Results:
* None.
*
* Side effects:
* The columnWidth and numCols parameters are filled in with their values.
*
*----------------------------------------------------------------------
*/
static void
GetColumnWidthInfo(aWindow, maxEntryWidth, columnWidth, numCols)
WishWindow *aWindow;
int maxEntryWidth;
int *columnWidth;
int *numCols;
{
int numToDisplay;
int numColsRequired;
int widthLeft;
if (maxEntryWidth < 0) {
*columnWidth = GetMaxEntryWidth(aWindow) + WISH_COLUMN_SPACING;
} else {
*columnWidth = maxEntryWidth + WISH_COLUMN_SPACING;
}
*numCols = aWindow->windowWidth / *columnWidth;
if (*numCols == 0) {
return ;
}
numToDisplay = aWindow->totalDisplayEntries - aWindow->firstElement + 1;
if (aWindow->numRows == 0) {
return ;
}
numColsRequired = numToDisplay / aWindow->numRows;
if (numToDisplay % aWindow->numRows != 0) {
numColsRequired++;
}
if (numColsRequired < *numCols) {
*numCols = numColsRequired;
}
if (*numCols == 0) {
return ;
}
widthLeft = aWindow->windowWidth - (*numCols * *columnWidth);
/*
* This could allow the last column to fail to meet the scroll bar by
* a number of pixels one less than the number of columns.
* We also add 1 pixel here so that entry window borders will overlap
* with the window borders if we start them at 1 pixel before the
* actual text area.
*/
*columnWidth += (widthLeft / *numCols) + 1;
return ;
}
/*
*----------------------------------------------------------------------
*
* FigureWindowSize --
*
* Figure out a good window size.
*
* Results:
* None.
*
* Side effects:
* The window size changes and stuff is laid out again to match.
*
*----------------------------------------------------------------------
*/
static void
FigureWindowSize(aWindow, maxEntryWidth)
WishWindow *aWindow;
int maxEntryWidth;
{
int maxWidth;
int width, height;
int columnWidth, numCols, numRows, numColsRequired;
columnWidth = maxEntryWidth;
maxWidth = wishRootWidth / 8 * 7;
width = maxWidth;
numCols = width / (columnWidth + WISH_COLUMN_SPACING);
if (numCols == 0) {
/* just set to max size */
}
for ( ; ; ){
/* Make it line up on column boundary -- no wasted space */
width = numCols * (columnWidth + WISH_COLUMN_SPACING);
height = width / 3 * 2; /* 2/3's of width */
numRows = height / aWindow->rowHeight;
if (aWindow->numRows == 0) {
/* just set to max size */
}
numColsRequired = aWindow->totalDisplayEntries / numRows;
if (aWindow->totalDisplayEntries % numRows != 0) {
numColsRequired++;
}
if (numColsRequired < numCols) {
numCols--;
} else {
break;
}
}
/* last shrinking may have gone too far since we shrank rows as well */
if (numColsRequired > numCols && (width + columnWidth +
WISH_COLUMN_SPACING <= maxWidth)) {
numCols++;
width += columnWidth + WISH_COLUMN_SPACING;
/* leave height and numRows alone */
}
/*
* This next will generate an ExposureMask event, but I'm not sure
* yet just where it fit in, so I may change some things.
* It is an incredible pain that I can't change the displayWindow
* to the correct dimensions and have the packer know to resize the
* parent window. Right now I have to resize to parent (surrounding)
* window to what I guess should be its size. I can't
* XGetGeometry() them here since they all seem to have a size of 1
* in Sx until some event occurs... IS THIS STILL TRUE IN X11???
*/
/*
* 2 titles, 2 regular bars, and 8 regular font heights for tx window.
*/
if (aWindow->windowWidth != width || aWindow->windowHeight != height) {
XWindowChanges changes;
changes.width = width + 1 + Sx_ScrollbarWidth();
changes.height = height +
(2 * Sx_DefaultHeight(wishDisplay, aWindow->titleFontPtr))
+ 3 + (10 * Sx_DefaultHeight(wishDisplay, aWindow->fontPtr));
XConfigureWindow(wishDisplay, aWindow->surroundingWindow,
CWWidth | CWHeight, &changes);
}
return;
}
/*
*----------------------------------------------------------------------
*
* WishDumpState --
*
* Dump the contents of the group and file lists to stderr for debugging.
*
* Results:
* None.
*
* Side effects:
* Stuff gets printed to stderr.
*
*----------------------------------------------------------------------
*/
void
WishDumpState(aWindow)
WishWindow *aWindow;
{
WishGroup *tmpGroupPtr;
WishFile *tmpFilePtr;
for (tmpGroupPtr = aWindow->groupList; tmpGroupPtr != NULL;
tmpGroupPtr = tmpGroupPtr->nextPtr) {
fprintf(stderr, "GROUP:\t%s\n", tmpGroupPtr->editHeader);
for (tmpFilePtr = tmpGroupPtr->fileList; tmpFilePtr != NULL;
tmpFilePtr = tmpFilePtr->nextPtr) {
fprintf(stderr, "\t\t%s %s\n", tmpFilePtr->name,
tmpFilePtr->attrPtr == NULL ? "NULL" : "attrs");
}
}
return;
}